package org.c41.util.log;

import java.io.File;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Hashtable;

import org.c41.util.Check;
import org.c41.util.time.TimeStamp;


public final class LogConfig {
	
	LogConfig(){}
	
	public void setLog(boolean b) {
		if(b){
			Log.logger=new LogOn();
		}
		else{
			Log.logger=new LogOff();
		}
	}
	
	private int defaultlevel = Log.DEBUG;
	private Object defaultTarget = System.err;
	private LogMessage defaultLogMessage = new LogMessage(){

		@Override
		public String debugMessage(String message, long time, String cl,
				String method, String file, int line, String thread, int level) {
			TimeStamp stamp = new TimeStamp(time);
			String levelname = "LEVEL "+String.valueOf(level);
			switch(level){
			case Log.TRACE: levelname= "TRACE";break;
			case Log.DEBUG: levelname= "DEBUG";break;
			case Log.INFO: levelname= "INFO";break;
			case Log.WARN: levelname= "WARN";break;
			case Log.ERROR: levelname= "ERROR";break;
			case Log.FATAL: levelname= "FATAL";break;
			}
			return stamp+" "+levelname+" ["+cl+"#"+method+" line "+line+"] : "+message+"\r\n";
		}

	};
	
	private final Hashtable<String, Object> targets = new Hashtable<>();
	private final Hashtable<String, LogMessage> logmessages = new Hashtable<>();
	private final Hashtable<String, Integer> loglevels = new Hashtable<>();
	
	public void setLogTarget(Class<?> cl, OutputStream out){
		Check.notNull(cl);
		Check.notNull(out);
		if(out instanceof PrintStream){
			targets.put(cl.getName(), out);
		}
		else{
			targets.put(cl.getName(), new PrintWriter(out,true));
		}
	}
	
	public void setLogTarget(Class<?> cl, Writer out){
		Check.notNull(cl);
		Check.notNull(out);
		targets.put(cl.getName(), out);
	}
	
	public void setLogTarget(Class<?> cl, File file){
		Check.notNull(cl);
		Check.notNull(file);
		targets.put(cl.getName(), file);
	}
	
	public void setLogMessage(Class<?> cl, LogMessage logmessage){
		Check.notNull(cl);
		Check.notNull(logmessage);
		logmessages.put(cl.getName(), logmessage);
	}
	
	public void setLogLevel(Class<?> cl, int level){
		Check.notNull(cl);
		loglevels.put(cl.getName(), level);
	}
	
	public void setDefaultLogTarget(OutputStream out){
		Check.notNull(out);
		if(out instanceof PrintStream){
			defaultTarget=out;
		}
		else{
			defaultTarget=new PrintWriter(out,true);
		}
	}
	
	public void setDefaultLogTarget(Writer out){
		Check.notNull(out);
		defaultTarget=out;
	}
	
	public void setDefaultLogTarget(File file){
		Check.notNull(file);
		defaultTarget=file;
	}
	
	public void setDefaultLogMessage(LogMessage logmessage){
		Check.notNull(logmessage);
		defaultLogMessage=logmessage;
	}
	
	public void setDefaultLogLevel(int level){
		this.defaultlevel=level;
	}
	
	Object inner_getLogTarget(String cl){
		Object target = targets.get(cl);
		if(target == null){
			target = defaultTarget;
		}
		return target;
	}
	
	LogMessage inner_getLogMessage(String cl){
		LogMessage logger = logmessages.get(cl);
		if(logger == null){
			logger = defaultLogMessage;
		}
		return logger;
	}

	int inner_getLogLevel(String cl) {
		Integer level = loglevels.get(cl);
		if(level==null){
			level=defaultlevel;
		}
		return level;
	}
	
}
